#ifndef _WX_MENU_H_BASE_
#define _WX_MENU_H_BASE_

#include "wx/defs.h"
#include "wx/list.h"
#include "wx/window.h"


#include "wx/menuitem.h"

class wxMenu;
class wxMenuBarBase;
class wxMenuBar;
class wxMenuItem;

WX_DECLARE_EXPORTED_LIST( wxMenu, wxMenuList );
WX_DECLARE_EXPORTED_LIST( wxMenuItem, wxMenuItemList );

class wxMenuBase : public wxEvtHandler {
  public:

    static wxMenu *New( const wxString& title = wxEmptyString, long style = 0 );


    wxMenuBase( const wxString& title, long style = 0 ) : m_title( title ) { Init( style ); }
    wxMenuBase( long style = 0 ) { Init( style ); }

    virtual ~wxMenuBase();
    wxMenuItem* Append( int itemid,
                        const wxString& text = wxEmptyString,
                        const wxString& help = wxEmptyString,
                        wxItemKind kind = wxITEM_NORMAL ) {
      return DoAppend( wxMenuItem::New( ( wxMenu * )this, itemid, text, help, kind ) );
    }


    wxMenuItem* AppendSeparator() { return Append( wxID_SEPARATOR, wxEmptyString ); }


    wxMenuItem* AppendCheckItem( int itemid, const wxString& text, const wxString& help = wxEmptyString ) {
      return Append( itemid, text, help, wxITEM_CHECK );
    }


    wxMenuItem* AppendRadioItem( int itemid, const wxString& text, const wxString& help = wxEmptyString ) {
      return Append( itemid, text, help, wxITEM_RADIO );
    }


    wxMenuItem* AppendSubMenu( wxMenu *submenu, const wxString& text, const wxString& help = wxEmptyString ) {
      return DoAppend( wxMenuItem::New( ( wxMenu * )this, wxID_ANY, text, help, wxITEM_NORMAL, submenu ) );
    }


    wxMenuItem* Append( wxMenuItem *item ) { return DoAppend( item ); }



    virtual void Break() { }


    wxMenuItem* Insert( size_t pos, wxMenuItem *item );


    wxMenuItem* Insert( size_t pos, int itemid, const wxString& text = wxEmptyString, const wxString& help = wxEmptyString,
                        wxItemKind kind = wxITEM_NORMAL ) {
      return Insert( pos, wxMenuItem::New( ( wxMenu * )this, itemid, text, help, kind ) );
    }


    wxMenuItem* InsertSeparator( size_t pos ) {
      return Insert( pos, wxMenuItem::New( ( wxMenu * )this, wxID_SEPARATOR ) );
    }


    wxMenuItem* InsertCheckItem( size_t pos, int itemid, const wxString& text, const wxString& help = wxEmptyString ) {
      return Insert( pos, itemid, text, help, wxITEM_CHECK );
    }


    wxMenuItem* InsertRadioItem( size_t pos, int itemid, const wxString& text, const wxString& help = wxEmptyString ) {
      return Insert( pos, itemid, text, help, wxITEM_RADIO );
    }


    wxMenuItem* Insert( size_t pos, int itemid, const wxString& text, wxMenu *submenu, const wxString& help = wxEmptyString ) {
      return Insert( pos, wxMenuItem::New( ( wxMenu * )this, itemid, text, help, wxITEM_NORMAL, submenu ) );
    }


    wxMenuItem* Prepend( wxMenuItem *item ) {
      return Insert( 0u, item );
    }


    wxMenuItem* Prepend( int itemid, const wxString& text = wxEmptyString, const wxString& help = wxEmptyString,
                         wxItemKind kind = wxITEM_NORMAL ) {
      return Insert( 0u, itemid, text, help, kind );
    }


    wxMenuItem* PrependSeparator() {
      return InsertSeparator( 0u );
    }


    wxMenuItem* PrependCheckItem( int itemid, const wxString& text, const wxString& help = wxEmptyString ) {
      return InsertCheckItem( 0u, itemid, text, help );
    }


    wxMenuItem* PrependRadioItem( int itemid, const wxString& text, const wxString& help = wxEmptyString ) {
      return InsertRadioItem( 0u, itemid, text, help );
    }


    wxMenuItem* Prepend( int itemid, const wxString& text, wxMenu *submenu, const wxString& help = wxEmptyString ) {
      return Insert( 0u, itemid, text, submenu, help );
    }




    wxMenuItem *Remove( int itemid ) { return Remove( FindChildItem( itemid ) ); }
    wxMenuItem *Remove( wxMenuItem *item );



    bool Delete( int itemid ) { return Delete( FindChildItem( itemid ) ); }
    bool Delete( wxMenuItem *item );


    bool Destroy( int itemid ) { return Destroy( FindChildItem( itemid ) ); }
    bool Destroy( wxMenuItem *item );





    size_t GetMenuItemCount() const { return m_items.GetCount(); }

    const wxMenuItemList& GetMenuItems() const { return m_items; }
    wxMenuItemList& GetMenuItems() { return m_items; }


    virtual int FindItem( const wxString& item ) const;
    wxMenuItem* FindItem( int itemid, wxMenu **menu = NULL ) const;


    wxMenuItem* FindItemByPosition( size_t position ) const;


    void Enable( int itemid, bool enable );
    bool IsEnabled( int itemid ) const;

    void Check( int itemid, bool check );
    bool IsChecked( int itemid ) const;

    void SetLabel( int itemid, const wxString& label );
    wxString GetLabel( int itemid ) const;

    virtual void SetHelpString( int itemid, const wxString& helpString );
    virtual wxString GetHelpString( int itemid ) const;





    virtual void SetTitle( const wxString& title ) { m_title = title; }
    const wxString GetTitle() const { return m_title; }


    void SetEventHandler( wxEvtHandler *handler ) { m_eventHandler = handler; }
    wxEvtHandler *GetEventHandler() const { return m_eventHandler; }


    void SetInvokingWindow( wxWindow *win ) { m_invokingWindow = win; }
    wxWindow *GetInvokingWindow() const { return m_invokingWindow; }


    long GetStyle() const { return m_style; }







    void UpdateUI( wxEvtHandler* source = ( wxEvtHandler* )NULL );



    wxMenuBar *GetMenuBar() const;


    virtual void Attach( wxMenuBarBase *menubar );
    virtual void Detach();


    bool IsAttached() const { return GetMenuBar() != NULL; }


    void SetParent( wxMenu *parent ) { m_menuParent = parent; }
    wxMenu *GetParent() const { return m_menuParent; }







    wxMenuItem *FindChildItem( int itemid, size_t *pos = NULL ) const;





    bool SendEvent( int itemid, int checked = -1 );






    void Append( int itemid,
                 const wxString& text,
                 const wxString& help,
                 bool isCheckable ) {
      Append( itemid, text, help, isCheckable ? wxITEM_CHECK : wxITEM_NORMAL );
    }


    wxMenuItem* Append( int itemid,
                        const wxString& text,
                        wxMenu *submenu,
                        const wxString& help = wxEmptyString ) {
      return DoAppend( wxMenuItem::New( ( wxMenu * )this, itemid, text, help,
                                        wxITEM_NORMAL, submenu ) );
    }

    void Insert( size_t pos,
                 int itemid,
                 const wxString& text,
                 const wxString& help,
                 bool isCheckable ) {
      Insert( pos, itemid, text, help, isCheckable ? wxITEM_CHECK : wxITEM_NORMAL );
    }

    void Prepend( int itemid,
                  const wxString& text,
                  const wxString& help,
                  bool isCheckable ) {
      Insert( 0u, itemid, text, help, isCheckable );
    }

    static void LockAccels( bool locked ) {
      ms_locked = locked;
    }

  protected:



    virtual wxMenuItem* DoAppend( wxMenuItem *item );
    virtual wxMenuItem* DoInsert( size_t pos, wxMenuItem *item );

    virtual wxMenuItem *DoRemove( wxMenuItem *item );
    virtual bool DoDelete( wxMenuItem *item );
    virtual bool DoDestroy( wxMenuItem *item );





    void Init( long style );


    void AddSubMenu( wxMenu *submenu );

    wxMenuBar     *m_menuBar;
    wxMenu        *m_menuParent;

    wxString       m_title;
    wxMenuItemList m_items;

    wxWindow      *m_invokingWindow;

    long           m_style;

    wxEvtHandler  *m_eventHandler;

    static bool      ms_locked;

    DECLARE_NO_COPY_CLASS( wxMenuBase )

  public:
    wxString GetLabelText( int itemid ) const { return wxMenuItem::GetLabelFromText( GetLabel( itemid ) ); }
};

class wxMenuBarBase : public wxWindow {
  public:
    wxMenuBarBase();
    virtual ~wxMenuBarBase();
    virtual bool Append( wxMenu *menu, const wxString& title );
    virtual bool Insert( size_t pos, wxMenu *menu, const wxString& title );
    size_t GetMenuCount() const { return m_menus.GetCount(); }
    wxMenu *GetMenu( size_t pos ) const;
    virtual wxMenu *Replace( size_t pos, wxMenu *menu, const wxString& title );
    virtual wxMenu *Remove( size_t pos );
    virtual void EnableTop( size_t pos, bool enable ) = 0;
    virtual bool IsEnabledTop( size_t ( pos ) ) const { return true; }
    virtual void SetLabelTop( size_t pos, const wxString& label ) = 0;
    virtual wxString GetLabelTop( size_t pos ) const = 0;
    virtual int FindMenuItem( const wxString& menu, const wxString& item ) const;
    virtual wxMenuItem* FindItem( int itemid, wxMenu **menu = NULL ) const;
    int FindMenu( const wxString& title ) const;
    void Enable( int itemid, bool enable );
    void Check( int itemid, bool check );
    bool IsChecked( int itemid ) const;
    bool IsEnabled( int itemid ) const;
    virtual bool IsEnabled() const { return wxWindow::IsEnabled(); }
    void SetLabel( int itemid, const wxString &label );
    wxString GetLabel( int itemid ) const;
    void SetHelpString( int itemid, const wxString& helpString );
    wxString GetHelpString( int itemid ) const;
    wxFrame *GetFrame() const { return m_menuBarFrame; }
    bool IsAttached() const { return GetFrame() != NULL; }
    virtual void Attach( wxFrame *frame );
    virtual void Detach();
    virtual bool Enable( bool enable = true ) { return wxWindow::Enable( enable ); }
    virtual void SetLabel( const wxString& s ) { wxWindow::SetLabel( s ); }
    virtual wxString GetLabel() const { return wxWindow::GetLabel(); }
    virtual bool AcceptsFocusFromKeyboard() const { return false; }
    virtual void UpdateMenus();
  protected:
    wxMenuList m_menus;
    wxFrame *m_menuBarFrame;
    DECLARE_NO_COPY_CLASS( wxMenuBarBase )
  public:
    void SetMenuLabel( size_t pos, const wxString& label ) { SetLabelTop( pos, label ); }
    wxString GetMenuLabelText( size_t pos ) const;

};

#ifdef wxUSE_BASE_CLASSES_ONLY
#define wxMenuItem wxMenuItemBase
#else
#include "wx/gtk/menu.h"
#endif

#endif
